using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using netCoreStudy.Attr;
using netCoreStudy.Attr.QueryAttr;
using static System.IO.File;
using static netCoreStudy.MyCommonMethod;

namespace netCoreStudy.Controllers
{
	/// <summary>
	/// 代码生成
	/// </summary>
	[ApiController]
	[Route("api/generateCode")]
	public class GenerateCodeController : ControllerBase
	{
		private readonly ILogger<GenerateCodeController> _logger;
		private readonly IMapper _mapper;

		public GenerateCodeController(ILogger<GenerateCodeController> logger,
			IMapper mapper)
		{
			_logger = logger;
			_mapper = mapper;
		}

		/// <summary>
		/// 生成网页 代码 
		/// </summary>
		/// <param name="entityName"></param>
		/// <returns></returns>
		[HttpGet("web/{entityName}")]
		public IActionResult GenerateWebCode(string entityName)
		{
			string[] baseEntityNames = {"user", "material", "menu", "modules", "permission", "role"};
			if (baseEntityNames.Contains(entityName.ToLower()))
			{
				return this.FailMsg("原有的网页 不能瞎搞……");
			}

			// 先让首字母大写
			entityName = entityName.CaseFirstLetter();
			string entityDir = Path.Combine(Directory.GetCurrentDirectory(), "Dto");
			//设置前端的路径 
			string webPath = "/home/ifnk/proj/baoji_inspection/InspectionWeb/src";

			DirectoryInfo folder = new DirectoryInfo(entityDir);
			IEnumerable<string> entityNames = folder.GetFiles("*.cs")
				.Select(x => Path.GetFileNameWithoutExtension(x.Name));
			if (entityNames.All(x => x.ToLower() != $"{entityName}Dto".ToLower()))
			{
				return this.FailMsg("未找到Dto!请先生成api代码再使用网页生成功能!");
			}

			Type dtoType = Type.GetType($"{GetAssemblyName()}.Dto.{entityName}Dto");
			Type addDtoType = Type.GetType($"{GetAssemblyName()}.Dto.Add{entityName}Dto");
			Type updateDtoType = Type.GetType($"{GetAssemblyName()}.Dto.Update{entityName}Dto");
			if (dtoType == null)
				return this.FailMsg($"失败!检查下路径下有没有这个 dto Type   {GetAssemblyName()}.Dto.{entityName}Dto");
			if (addDtoType == null)
				return this.FailMsg($"失败!检查下路径下有没有这个 dto Type   {GetAssemblyName()}.Dto.{entityName}Dto");
			if (updateDtoType == null)
				return this.FailMsg($"失败!检查下路径下有没有这个 dto Type   {GetAssemblyName()}.Dto.{entityName}Dto");
			// 获取类 中文名(注释特性)
			string entityCommentName = dtoType.GetCommentName();

			// 获取非基类 属性 列表  Dto 
			PropertyInfo[] propertyInfos = dtoType
				.GetProperties()
				.Where(x => x.DeclaringType.Name != "BaseDto")
				.ToArray();
			propertyInfos.Select(x => x.Name).JsonCW();
			// 生成 api.js (src/api)
			GenerateWebSrcApi(entityName, entityCommentName, Path.Combine(webPath, "api"));
			// 生成 index.vue  (src/views/className/index.vue)
			GenerateWebVue(entityName, propertyInfos, entityCommentName, webPath, addDtoType, updateDtoType);

			return this.SuccessMsg("生成前端代码成功!");
		}

		/// <summary>
		/// 生成后端代码 
		/// </summary>
		/// <param name="entityName"></param>
		/// <returns></returns>
		[HttpGet("{entityName}")]
		public IActionResult GenerateApiCode(string entityName)
		{
			string[] baseEntityNames = {"user", "material", "menu", "modules", "permission", "role"};
			if (baseEntityNames.Contains(entityName))
			{
				return this.FailMsg("原有的实体 不能瞎搞……");
			}

			// 先让首字母大写
			entityName = entityName.CaseFirstLetter();

			string entityDir = Path.Combine(Directory.GetCurrentDirectory(), "Entities");

			//设置前端的路径 
			DirectoryInfo folder = new DirectoryInfo(entityDir);
			string[] entityNames = folder.GetFiles("*.cs")
				.Select(x => Path.GetFileNameWithoutExtension(x.Name)).ToArray();
			if (entityNames.All(x => x.ToLower() != entityName.ToLower()))
			{
				return this.FailMsg("未找到实体!");
			}

			// 获取类型
			Type type = Type.GetType($"{GetAssemblyName()}.Entities.{entityName}");

			if (type == null)
			{
				return this.FailMsg($"失败!检查下路径下有没有这个 Type   {GetAssemblyName()}.Entities.{entityName}");
			}

			// 根据类型 获取除继承基类 以外 的所有 属性 
			PropertyInfo[] propertyInfos = type
				.GetProperties()
				.Where(x => x.DeclaringType != null && x.DeclaringType.Name != "BaseEntity")
				.ToArray();
			// 生成 Dto.cs 
			GenerateDto(entityName, propertyInfos, entityNames, type);
			// 生成 AddDto.cs 
			GenerateAddDto(entityName, propertyInfos, entityNames, type.GetCommentName());
			// 生成 AddDto.cs 
			GenerateUpdateDto(entityName, propertyInfos, entityNames, type.GetCommentName());
			// 生成 IService.cs 
			GenerateIService(entityName);
			// 生成 Service.cs 
			GenerateService(entityName);
			// 生成 Profile.cs 
			GenerateProfile(entityName);
			// 生成 Parameter.cs 
			GenerateParameter(entityName);
			// 生成 Controller.cs 
			GenerateController(entityName);
			// 生成 AddValidator.cs 
			GenerateAddValidator(entityName, propertyInfos, entityNames);
			// 生成 UpdateValidator.cs 
			GenerateUpdateValidator(entityName, propertyInfos, entityNames);
			return this.SuccessMsg("生成成功!请重启后台服务!");
		}

		private void GenerateUpdateValidator(string entityName, PropertyInfo[] propertyInfos, string[] entityNames)
		{
			string updateValidatorStr = $@"
using System.Linq;
using FluentValidation;
using {GetAssemblyName()}.Dto;
using {GetAssemblyName()}.IService;

namespace {GetAssemblyName()}.DtoValidator
{{
	public class Update{entityName}Validator : AbstractValidator<Update{entityName}Dto>
	{{
		public Update{entityName}Validator(I{entityName}Service userService)
		{{";
			foreach (PropertyInfo prop in propertyInfos)
			{
				// 过滤掉实体(实体带include )
				if (prop.GetCustomAttribute<IncludeAttribute>() != null) continue;
				CommentAttribute commentAttr = prop.GetCustomAttribute<CommentAttribute>();
				if (commentAttr == null) continue;
				// comment 特性 中 addShow 是 false 就跳过生成 
				if (commentAttr.AddShow == false) continue;

				// 如果是数字开头 的话 ，要判断 他是不是0 
				if (prop.PropertyType.Name.StartsWith("Int"))
				{
					updateValidatorStr += $@"
			RuleFor(x => x.{prop.Name})
				.NotNull()
				.NotEmpty()
				.WithName(""{prop.GetCommentName()}"")
				.WithMessage(""验证不通过,{{PropertyName}}不能为空!"")
				.Must(x => x.CheckNotZero())
				.WithMessage(""验证不通过,{{PropertyName}}数字类型不能为0"")
				;
";
				}
				else
				{
					updateValidatorStr += $@"
			RuleFor(x => x.{prop.Name})
				.NotNull()
				.NotEmpty()
				.WithName(""{prop.GetCommentName()}"")
				.WithMessage(""验证不通过,{{PropertyName}}不能为空!"")
				;
";
				}
			}

			updateValidatorStr += $@"
		}}
	}}
}}
";
			// 写出 UpdateValidator  
			WriteAllText(
				Path.Combine(Directory.GetCurrentDirectory(), "DtoValidator", $"Update{entityName}Validator.cs"),
				updateValidatorStr);
		}

		private void GenerateAddValidator(string entityName, PropertyInfo[] propertyInfos, string[] entityNames)
		{
			string AddValidatorStr = $@"
using System.Linq;
using FluentValidation;
using {GetAssemblyName()}.Dto;
using {GetAssemblyName()}.IService;

namespace {GetAssemblyName()}.DtoValidator
{{
	public class Add{entityName}Validator : AbstractValidator<Add{entityName}Dto>
	{{
		public Add{entityName}Validator(I{entityName}Service userService)
		{{";
			foreach (PropertyInfo prop in propertyInfos)
			{
				// 过滤掉实体(实体带include )
				if (prop.GetCustomAttribute<IncludeAttribute>() != null) continue;
				CommentAttribute commentAttr = prop.GetCustomAttribute<CommentAttribute>();
				if (commentAttr == null) continue;
				// comment 特性 中 addShow 是 false 就跳过生成 
				if (commentAttr.AddShow == false) continue;
				// 如果是数字开头 的话 ，要判断 他是不是0 
				if (prop.PropertyType.Name.StartsWith("Int"))
				{
					AddValidatorStr += $@"
			RuleFor(x => x.{prop.Name})
				.NotNull()
				.NotEmpty()
				.WithName(""{prop.GetCommentName()}"")
				.WithMessage(""验证不通过,{{PropertyName}}不能为空!"")
				.Must(x => x.CheckNotZero())
				.WithMessage(""验证不通过,{{PropertyName}}数字类型不能为0"")
				;
";
				}
				else
				{
					AddValidatorStr += $@"
			RuleFor(x => x.{prop.Name})
				.NotNull()
				.NotEmpty()
				.WithName(""{prop.GetCommentName()}"")
				.WithMessage(""验证不通过,{{PropertyName}}不能为空!"")
				;
";
				}
			}

			AddValidatorStr += $@"
		}}
	}}
}}
";

			// 写出 AddValidator  
			WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "DtoValidator", $"Add{entityName}Validator.cs"),
				AddValidatorStr);
		}


		/// <summary>
		/// 生成 web 端 网页 vue 
		/// </summary>
		/// <param name="entityName">实体class 名称 </param>
		/// <param name="dtoPropInfos">实体的属性列表</param>
		/// <param name="entityCommentName">实体class 注释</param>
		/// <param name="webPath"></param>
		/// <param name="addDtoType">addDto type</param>
		/// <param name="updateDtoType">addDto type</param>
		private void GenerateWebVue(string entityName, PropertyInfo[] dtoPropInfos, string entityCommentName,
			string webPath, Type addDtoType, Type updateDtoType)
		{
			string vueStr = $@"
<template>
  <div class=""app-container"">
    <el-row :gutter=""10"" style=""margin-bottom: 15px"">
      <el-col :span=""5"">
        <el-input v-model=""listQuery.searchKey"" placeholder=""请输入关键词"" clearable/>
      </el-col>

      <el-col :span=""1.5"">
        <el-button  type=""primary"" icon=""el-icon-search"" @click=""getList"">搜索</el-button>
      </el-col>
      <el-col :span=""1.5"">
        <el-button  type=""primary"" icon=""el-icon-plus"" @click=""addDialogVis = true"">添加</el-button>
      </el-col>
    </el-row>
    <!--表格-->
    <el-table :data=""tableData"" border style=""width: 100%"">
      <el-table-column prop=""id"" label=""id"" />";
			foreach (PropertyInfo propInfo in dtoPropInfos)
			{
				//如果 结尾有Id 字段的话 就 不在 网页上面显示
				if (propInfo.Name.EndsWith("Id")) continue;
				vueStr += $@"
      <el-table-column label=""{propInfo.GetCommentName()}""><template slot-scope=""{{row}}"">{{{{row.{propInfo.Name.LowerCaseFirstLetter()}}}}}</template></el-table-column>
";
			}

			vueStr += $@"
      <el-table-column prop=""createTimeStr"" label=""创建时间"" />
      <el-table-column label=""操作"">
        <template scope=""scope"">
          <el-button size=""mini"" type=""primary"" @click=""handleEdit(scope.row.id)"">编辑</el-button>
          <el-button size=""mini"" type=""danger"" @click=""handleDel(scope.row.id)"">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <!--分页-->
    <pagination
      v-show=""totalCount > 0""
      :total=""totalCount""
      :page.sync=""listQuery.pageIndex""
      :limit.sync=""listQuery.pageSize""
      @pagination=""getList""
    />
    <!--dialog-添加{entityCommentName}-->
    <el-dialog title=""添加{entityCommentName}"" :visible.sync=""addDialogVis"" width=""30%"">
      <el-form :model=""addForm"" label-width=""80px"" ref=""addForm"">";
			foreach (PropertyInfo propInfo in addDtoType.GetProperties())
			{
				// 数字 的话 生成 select 框
				if (propInfo.PropertyType.Name == "Int32" || propInfo.PropertyType.Name == "Int64")
				{
					// date 结尾的话 是日期选择框
					if (propInfo.Name.EndsWith("Date"))
					{
						vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
		  <el-date-picker v-model=""dateTs"" @change=""selectDate"" value-format=""timestamp"" type=""date"" placeholder=""请选择{propInfo.GetCommentName()}"" />
        </el-form-item>";
					}
					else
					{
						vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
		  <el-select v-model=""addForm.{propInfo.Name.LowerCaseFirstLetter()}"" placeholder=""请选择{propInfo.GetCommentName()}"">
            <el-option label=""请选择{propInfo.GetCommentName()}"" :value=""0"" />
		    <el-option v-for=""item in deviceTypes"" :key=""item.id"" :label=""item.name"" :value=""item.id""/>
		  </el-select>
        </el-form-item>";
					}
				}

				// string 的话 生成 input 框
				if (propInfo.PropertyType.Name == "String")
				{
					vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
          <el-input v-model=""addForm.{propInfo.Name.LowerCaseFirstLetter()}""/>
        </el-form-item>";
				}

				// string 的话 生成 radio 
				if (propInfo.PropertyType.Name == "Boolean")
				{
					vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
        </el-form-item>";
				}

				// list 开头的 则 生成 多选 select 框
				if (propInfo.PropertyType.Name.StartsWith("List"))
				{
					vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
        </el-form-item>";
				}
			}

			vueStr += $@" 
      </el-form>
      <span slot=""footer"" class=""dialog-footer"">
          <el-button @click=""addDialogVis = false"">取消</el-button>
          <el-button type=""primary"" @click=""addSubmit"">确定</el-button>
      </span>
    </el-dialog>
    <!--dialog-编辑{entityCommentName}-->
    <el-dialog title=""编辑{entityCommentName}"" :visible.sync=""editDialogVis"" width=""30%"">
      <el-form :model=""editForm"" label-width=""80px"" ref=""editForm""> ";
			foreach (PropertyInfo propInfo in addDtoType.GetProperties())
			{
				// 数字 的话 生成 select 框
				if (propInfo.PropertyType.Name == "Int32" || propInfo.PropertyType.Name == "Int64")
				{
					// date 结尾的话 是日期选择框
					if (propInfo.Name.EndsWith("Date"))
					{
						vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
		  <el-date-picker v-model=""dateTs"" @change=""selectDate"" value-format=""timestamp"" type=""date"" placeholder=""请选择{propInfo.GetCommentName()}"" />
        </el-form-item>";
					}
					else
					{
						vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
		  <el-select v-model=""editForm.{propInfo.Name.LowerCaseFirstLetter()}"" placeholder=""请选择{propInfo.GetCommentName()}"">
            <el-option label=""请选择{propInfo.GetCommentName()}"" :value=""0"" />
		    <el-option v-for=""item in deviceTypes"" :key=""item.id"" :label=""item.name"" :value=""item.id""/>
		  </el-select>
        </el-form-item>";
					}
				}

				// string 的话 生成 input 框
				if (propInfo.PropertyType.Name == "String")
				{
					vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
          <el-input v-model=""editForm.{propInfo.Name.LowerCaseFirstLetter()}""/>
        </el-form-item>";
				}

				// string 的话 生成 radio 
				if (propInfo.PropertyType.Name == "Boolean")
				{
					vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
        </el-form-item>";
				}

				// list 开头的 则 生成 多选 select 框
				if (propInfo.PropertyType.Name.StartsWith("List"))
				{
					vueStr += $@"
        <el-form-item label=""{propInfo.GetCommentName()}"" prop=""{propInfo.Name.LowerCaseFirstLetter()}"">
        </el-form-item>";
				}
			}

			vueStr += $@"
      </el-form>
      <span slot=""footer"" class=""dialog-footer"">
          <el-button @click=""editDialogVis = false"">取消</el-button>
          <el-button type=""primary"" @click=""editSubmit"">确定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import {{mapGetters}} from ""vuex""
import Pagination from ""@/components/Pagination""
import {{
  get{entityName}s,
  update{entityName},
  getOne{entityName}ById,
  delete{entityName}ById,
  addOne{entityName}
}} from ""@/api/{entityName.LowerCaseFirstLetter()}"";

export default {{
  name: ""{entityName}"",
  components: {{Pagination}},
  data() {{
    return {{
      // 日期时间戳
      dateTs:'',
      // 添加 dialog Vis
      addDialogVis: false,
      // 编辑 dialog Vis
      editDialogVis: false,
      // {entityCommentName} 总数
      totalCount: 0,
      // {entityCommentName} 列表 查询参数
      listQuery: {{
        searchKey: """", //关键字搜索
        pageIndex: 1,
        pageSize: 20,
      }},
      // {entityCommentName} 表格数据
      tableData: [],
      //新增界面数据
      addForm: {{";
			foreach (PropertyInfo propInfo in addDtoType.GetProperties())
			{
				vueStr += $@" 
			  //{propInfo.GetCommentName()}
			  {propInfo.Name.LowerCaseFirstLetter()}: {propInfo.PropStrWebConvert()},";
			}

			vueStr += $@" 
      }},
      //编辑界面数据
      editForm: {{";
			foreach (PropertyInfo propInfo in updateDtoType.GetProperties())
			{
				vueStr += $@"
			  //{propInfo.GetCommentName()}
			  {propInfo.Name.LowerCaseFirstLetter()}: {propInfo.PropStrWebConvert()},";
			}

			vueStr += $@" 
      }},
	  // 占位用，根据自己需求改
      deviceTypes: [{{
        id: 1,
        name: '占位用,自己改'
      }}, {{
        id: 2,
        name: '能力有限'
      }}, {{
        id: 3,
        name: '做不出来'
      }}],

    }}
  }},
  created() {{
    this.getList();

  }},
  computed: {{
    ...mapGetters([""imageUrl"", ""uploadImgUrl""])
  }},
  methods: {{
    // 获取 {entityCommentName} 列表
    async getList() {{
      const {{body: res}} = await get{entityName}s(this.listQuery);
      this.totalCount = res.totalCount;
      this.tableData = res.body;
    }},
    // 添加 {entityCommentName}
    async addSubmit() {{
      const {{body: res}} = await addOne{entityName}(this.addForm)
      this.$message.success('添加成功!')
      // 重置 添加 表单
      this.$refs['addForm'].resetFields();
      // 关闭 add dialog
      this.addDialogVis = false;
      // 刷新列表数据
      await this.getList();
    }},
    // 编辑 {entityCommentName}
    async editSubmit() {{
      const {{body: res}} = await update{entityName}(this.editForm.id, this.editForm)
      this.$message.success('编辑成功!')
      // 重置 添加 表单
      this.$refs['editForm'].resetFields();
      // 关闭 dit dialog
      this.editDialogVis = false;
      // 刷新列表数据
      await this.getList();
    }},
    // 编辑前的操作
    async handleEdit(id) {{
      const {{body: res}} = await getOne{entityName}ById(id)
      this.editForm = res;
      this.editDialogVis = true;
    }},
    // 删除一个{entityCommentName}
    async handleDel(id) {{
      const {{body: res}} = await delete{entityName}ById(id);
      await this.getList();
      this.$message.success('删除成功!');
    }},
    selectDate(date) {{
      this.addForm.taskDate = date == null ? 0 : date;
      this.editForm.taskDate = date == null ? 0 : date;
    }},

  }}
}}
</script>
<style></style>
";

			// 没有文件夹先创建 
			string dir = Path.Combine(webPath, "views", entityName.LowerCaseFirstLetter());
			if (!Directory.Exists(dir))
			{
				Directory.CreateDirectory(dir);
			}

			WriteAllText(Path.Combine(dir, "index.vue"),
				vueStr);
		}


		/// <summary>
		///  生成web 端 api.js 
		/// </summary>
		/// <param name="entityName">类英语名</param>
		/// <param name="entityCommentName">类中文名</param>
		/// <param name="outDir">输出目录</param>
		private void GenerateWebSrcApi(string entityName, string entityCommentName, string outDir)
		{
			entityName = entityName.LowerCaseFirstLetter();
			string entityNameCase = entityName.CaseFirstLetter();
			string apiStr = $@"
import request from '@/utils/request'

//根据Id获取单个{entityCommentName}
export function getOne{entityNameCase}ById(id) {{
  return request({{
    url: `api/{entityName}/${{id}}`,
    method: 'get',
    params: id
  }})
}}

//根据id 删除{entityCommentName}
export function delete{entityNameCase}ById(id) {{
    return request({{
      url: `api/{entityName}/${{id}}`,
      method: 'delete',
      params: id
    }})
  }}

//根据id 更新{entityCommentName}
export function update{entityNameCase}(id,data) {{
    return request({{
      url: `api/{entityName}/${{id}}`,
      method: 'put',
      data
    }})
  }}
//添加一条数据-{entityCommentName}
export function addOne{entityNameCase}(data) {{
    return request({{
      url: 'api/{entityName}',
      method: 'post',
      data
      // params: query
    }})
  }}
//查询所有数据-{entityCommentName}
export function get{entityNameCase}s(query) {{
    return request({{
      url: 'api/{entityName}',
      method: 'get',
      params: query
    }})
  }}
";

			// 写出 web api js 
			WriteAllText(Path.Combine(outDir, $"{entityName.LowerCaseFirstLetter()}.js"),
				apiStr);
		}

		/// <summary>
		/// 生成 IService.cs
		/// </summary>
		/// <param name="entityName"></param>
		/// <returns></returns>
		private void GenerateIService(string entityName)
		{
			string iServStr = $@"
using {GetAssemblyName()}.Entities;
using {GetAssemblyName()}.Entities.Base;

namespace {GetAssemblyName()}.IService
{{
	public interface I{entityName}Service : IBaseService<{entityName}>
	{{
	}}
}}
";
			// 写出 IService  
			WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "IService", $"I{entityName}Service.cs"),
				iServStr);
		}

		/// <summary>
		/// 生成Service.cs
		/// </summary>
		/// <param name="entityName"></param>
		/// <returns></returns>
		private void GenerateService(string entityName)
		{
			string servStr = $@"
using AutoMapper;
using Microsoft.Extensions.Logging;
using {GetAssemblyName()}.Entities;
using {GetAssemblyName()}.Entities.Base;
using {GetAssemblyName()}.IService;

namespace {GetAssemblyName()}.Service
{{
	public class {entityName}Service : BaseService<{entityName}>, I{entityName}Service
	{{
		public {entityName}Service(ApiDbContext context, IMapper mapper, ILogger<{entityName}Service> logger) : base(
			context, mapper, logger)
		{{
		}}
	}}
}}
";
			// 写出 IService  
			WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "Service", $"{entityName}Service.cs"),
				servStr);
		}

		/// <summary>
		/// 初始化 Service 的 string builder 
		/// </summary>
		/// <param name="entityName"></param>
		/// <returns></returns>
		private void GenerateProfile(string entityName)
		{
			// using {GetAssemblyName()}.Dto.User;
			// using {GetAssemblyName()}.Entities;
			// using {GetAssemblyName()}.Entities.Base;
			string profileStr = $@"
using {GetAssemblyName()}.Dto;
using {GetAssemblyName()}.Entities;
using {GetAssemblyName()}.Entities.Base;

namespace {GetAssemblyName()}.Profile
{{
	public class {entityName}Profile : BaseProfile<{entityName}, {entityName}Dto, Add{entityName}Dto, Update{entityName}Dto>
	{{
		public {entityName}Profile()
		{{

		}}
	}}
}}
";
			// 写出 Profile
			WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "Profile", $"{entityName}Profile.cs"),
				profileStr);
		}

		/// <summary>
		/// 生成parameter 
		/// </summary>
		/// <param name="entityName"></param>
		/// <returns></returns>
		private void GenerateParameter(string entityName)
		{
			string paramStr = $@"
using {GetAssemblyName()}.Attr.QueryAttr;
using {GetAssemblyName()}.Entities.Base;

namespace {GetAssemblyName()}.Entities.Parameter
{{
	public class {entityName}Parameter : BaseParameter
	{{
	}}
}}
";
			// 写出 Parameter
			WriteAllText(
				Path.Combine(Directory.GetCurrentDirectory(), "Entities", "Parameter", $"{entityName}Parameter.cs"),
				paramStr);
		}

		/// <summary>
		/// 生成controller
		/// </summary>
		/// <param name="entityName"></param>
		/// <returns></returns>
		private void GenerateController(string entityName)
		{
			string controllerStr = $@"
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using {GetAssemblyName()}.Dto;
using {GetAssemblyName()}.Entities;
using {GetAssemblyName()}.Entities.Base;
using {GetAssemblyName()}.Entities.Parameter;

namespace {GetAssemblyName()}.Controllers
{{
	[ApiController]
	[Route(""api/{entityName.LowerCaseFirstLetter()}"")]
	public class {entityName}Controller : BaseController<{entityName}, {entityName}Dto, {entityName}Parameter, Add{entityName}Dto,
		Update{entityName}Dto>
	{{
		public {entityName}Controller(ILogger<{entityName}Controller> logger, IBaseService<{entityName}> baseService,
			IMapper mapper) : base(logger, baseService, mapper)
		{{
		}}
	}}
}}
";
			// 写出 Controller
			WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "Controllers", $"{entityName}Controller.cs"),
				controllerStr);
		}

		/// <summary>
		/// 生成dto.cs
		/// </summary>
		/// <param name="entityName"></param>
		/// <param name="props">属性列表</param>
		/// <param name="entityNames"></param>
		/// <param name="type"></param>
		/// <returns></returns>
		private void GenerateDto(string entityName, PropertyInfo[] props, string[] entityNames, Type type)
		{
			string dtoStr = $@"
using System.Collections.Generic;
using {GetAssemblyName()}.Entities.Base;
using {GetAssemblyName()}.Dto;
using {GetAssemblyName()}.Attr;
using {GetAssemblyName()}.Dto.User;

namespace {GetAssemblyName()}.Dto
{{
	[Comment(""{type.GetCommentName()}"")]
	public class {entityName}Dto : BaseDto
	{{
";
			foreach (PropertyInfo prop in props)
			{
				// 系统自带的 类型 要转换 下
				if (prop.PropertyType.Namespace.StartsWith("System"))
				{
					dtoStr += $@" 
		/// <summary>
		/// {prop.GetCommentName()}
		/// </summary>
		[Comment(""{prop.GetCommentName()}"")]
		public {prop.SystemStrConvert()} {prop.Name} {{get;set;}} 
";
				}
				else
				{
					dtoStr += $@"
		/// <summary>
		/// {prop.GetCommentName()}
		/// </summary>
		[Comment(""{prop.GetCommentName()}"")]
		public {prop.PropertyType.Name.ProjStrConvert(entityNames)} {prop.Name} {{get;set;}}
";
				}
			}

			dtoStr += $@"
	}}
}}
";

			WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "Dto", $"{entityName}Dto.cs"), dtoStr);
		}

		/// <summary>
		/// 生成 addDto.cs 
		/// </summary>
		/// <param name="entityName"></param>
		/// <param name="props"></param>
		/// <param name="entityNames"></param>
		/// <param name="entityTypeName"></param>
		/// <returns></returns>
		private void GenerateAddDto(string entityName, PropertyInfo[] props, string[] entityNames,
			string entityTypeName)
		{
			string addDtoStr = $@"
using System.Collections.Generic;
using {GetAssemblyName()}.Attr;

namespace {GetAssemblyName()}.Dto
{{
	/// <summary>
	/// 添加{entityTypeName} Dto
	/// </summary>
	[Comment(""添加{entityTypeName}"")]
	public class Add{entityName}Dto
	{{
";
			// public string Name {{ get; set; }}
			foreach (PropertyInfo prop in props)
			{
				IncludeAttribute includeAttribute = prop.GetCustomAttribute<IncludeAttribute>();
				// 如果include 里面 的 thenInclude 是空的话 跳过
				if (includeAttribute != null && includeAttribute.FullInclude == null) continue;
				CommentAttribute commentAttr = prop.GetCustomAttribute<CommentAttribute>();
				if (commentAttr == null) continue;
				// comment 特性 中 addShow 是 false 就跳过生成 
				if (commentAttr.AddShow == false) continue;
				// 如果是list ,一定是 多对多的! 此时 将 list<T> 转成 list<long> id 类型 
				addDtoStr += prop.PropertyType.Name.StartsWith("List")
					? $@"
		/// <summary>
		/// {prop.GetCommentName()}Ids
		/// </summary>
		[Comment(""{prop.GetCommentName()}"")]
		public List<long> {prop.Name} {{get;set;}}
"
					: $@"
		/// <summary>
		/// {prop.GetCommentName()}
		/// </summary>
		[Comment(""{prop.GetCommentName()}"")]
		public {prop.SystemStrConvert()} {prop.Name} {{get;set;}}
";
			}

			addDtoStr += $@"
	}}
}}
";
			WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "Dto", $"Add{entityName}Dto.cs"), addDtoStr);
		}

		/// <summary>
		/// 生成 updateDto.cs 
		/// </summary>
		/// <param name="entityName"></param>
		/// <param name="props"></param>
		/// <param name="entityNames"></param>
		/// <param name="EntityTypeName"></param>
		/// <returns></returns>
		private void GenerateUpdateDto(string entityName, PropertyInfo[] props, string[] entityNames,
			string EntityTypeName)
		{
			string updateDtoStr = $@"
using System.Collections.Generic;
using {GetAssemblyName()}.Attr;

namespace {GetAssemblyName()}.Dto
{{
	/// <summary>
	/// 更新{EntityTypeName} Dto
	/// </summary>
	[Comment(""更新{EntityTypeName}"")]
	public class Update{entityName}Dto
	{{
";
			foreach (PropertyInfo prop in props)
			{
				IncludeAttribute includeAttribute = prop.GetCustomAttribute<IncludeAttribute>();
				// 如果include 里面 的 thenInclude 是空的话 跳过
				if (includeAttribute != null && includeAttribute.FullInclude == null) continue;
				CommentAttribute commentAttr = prop.GetCustomAttribute<CommentAttribute>();
				if (commentAttr == null) continue;
				// comment 特性 中 addShow 是 false 就跳过生成 
				if (commentAttr.AddShow == false) continue;
				// 如果是list ,一定是 多对多的! 此时 将 list<T> 转成 list<long> id 类型 
				updateDtoStr += prop.PropertyType.Name.StartsWith("List")
					? $@"
		/// <summary>
		/// {prop.GetCommentName()}Ids
		/// </summary>
		[Comment(""{prop.GetCommentName()}"")]
		public List<long> {prop.Name} {{get;set;}}
"
					: $@"
		/// <summary>
		/// {prop.GetCommentName()} 
		/// </summary>
		[Comment(""{prop.GetCommentName()}"")]
		public {prop.SystemStrConvert()} {prop.Name} {{get;set;}}
";
			}

			updateDtoStr += $@"
	}}
}}
";
			WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "Dto", $"Update{entityName}Dto.cs"),
				updateDtoStr);
		}
	}
}